package com.price.common.eventbus

import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import com.price.common.extend.doCustomCrashListener
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.MutableSharedFlow
import java.util.concurrent.ConcurrentHashMap

@OptIn(DelicateCoroutinesApi::class)
object FlowEventBus {

    //用HashMap存储SharedFlow
    private val flowEvents = ConcurrentHashMap<String, MutableSharedFlow<Any>>()

    //获取Flow，当相应Flow不存在时创建
    fun getFlow(key: String): MutableSharedFlow<Any> {
        return flowEvents[key] ?: MutableSharedFlow<Any>().also { flowEvents[key] = it }
    }

    // 发送事件
    fun post(event: Any) {
        MainScope().launch {
            getFlow(event.javaClass.simpleName).emit(event)
        }
    }

    fun post(event: Any, delay: Long = 0) {
        MainScope().launch {
            delay(delay)
            getFlow(event.javaClass.simpleName).emit(event)
        }
    }

    fun postAsy(event: Any) {
        GlobalScope.launch(Dispatchers.IO) {
            getFlow(event.javaClass.simpleName).emit(event)
        }
    }

    // 订阅事件
    inline fun <reified T : Any> observe(
        lifecycleOwner: LifecycleOwner,
        minState: Lifecycle.State = Lifecycle.State.CREATED,
        dispatcher: CoroutineDispatcher = Dispatchers.Main,
        crossinline onReceived: (T) -> Unit
    ) = lifecycleOwner.lifecycleScope.launch(dispatcher) {
        kotlin.runCatching {
            getFlow(T::class.java.simpleName).collect {
                if (lifecycleOwner.lifecycle.currentState >= minState) {
                    if (it is T) onReceived(it)
                }
            }
        }.onFailure {
            doCustomCrashListener?.onCrash(it)
        }
    }

    //协程内
    fun register(
        lifecycleOwner: LifecycleOwner,
        any: Any,
        minState: Lifecycle.State = Lifecycle.State.CREATED,
        dispatcher: CoroutineDispatcher = Dispatchers.Main,
        action: (Any) -> Unit
    ) {
//        lifecycleOwner.lifecycle.addObserver(LifecycleObserver)
        lifecycleOwner.lifecycleScope.launch(dispatcher) {
            kotlin.runCatching {
                getFlow(any2Key(any)).collect {
                    if (lifecycleOwner.lifecycle.currentState >= minState) {
                        action(it)
                    }
                }
            }.onFailure {
                doCustomCrashListener?.onCrash(it)
            }
        }
    }

    //方便java调用
    //FlowEventBus.INSTANCE.register(this, TestEvent.class,new Function1<Object, Unit>() {
    //FlowEventBus.INSTANCE.register(this, new TestEvent(""),new Function1<Object, Unit>() {
    //FlowEventBus.register(this,TestEvent::class.java)
    //在Application中需要implementation "androidx.lifecycle:lifecycle-process:2.6.0" 重写getLifecycle
    fun register(
        lifecycleOwner: LifecycleOwner,
        any: Any,
        minState: Lifecycle.State = Lifecycle.State.CREATED,
        action: (Any) -> Unit
    ) {
//        lifecycleOwner.lifecycle.addObserver(LifecycleObserver)
        lifecycleOwner.lifecycleScope.launch(Dispatchers.Main) {
            kotlin.runCatching {
                getFlow(any2Key(any)).collect {
                    if (lifecycleOwner.lifecycle.currentState >= minState) {
                        action(it)
                    }
                }
            }.onFailure {
                doCustomCrashListener?.onCrash(it)
            }
        }
    }

    fun register(
        lifecycleOwner: LifecycleOwner,
        any: Any,
        action: (Any) -> Unit
    ) {
        lifecycleOwner.lifecycleScope.launch(Dispatchers.Main) {
            kotlin.runCatching {
                getFlow(any2Key(any)).collect {
                    if (lifecycleOwner.lifecycle.currentState >= Lifecycle.State.CREATED) {
                        action(it)
                    }
                }
            }.onFailure {
                doCustomCrashListener?.onCrash(it)
            }
        }
    }

    fun registerAsy(
        lifecycleOwner: LifecycleOwner,
        any: Any,
        action: (Any) -> Unit
    ) {
        lifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
            kotlin.runCatching {
                getFlow(any2Key(any)).collect {
                    if (lifecycleOwner.lifecycle.currentState >= Lifecycle.State.CREATED) {
                        action(it)
                    }
                }
            }.onFailure {
                doCustomCrashListener?.onCrash(it)
            }
        }
    }

    fun registerAsy(
        lifecycleOwner: LifecycleOwner,
        any: Any,
        minState: Lifecycle.State = Lifecycle.State.CREATED,
        action: (Any) -> Unit
    ) {
        lifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
            kotlin.runCatching {
                getFlow(any2Key(any)).collect {
                    if (lifecycleOwner.lifecycle.currentState >= minState) {
                        action(it)
                    }
                }
            }.onFailure {
                doCustomCrashListener?.onCrash(it)
            }
        }
    }

    private fun any2Key(any: Any): String {
        val key = when (any) {
            is Class<*> -> {
                any.simpleName
            }

            is String -> {
                any;
            }

            else -> {
                any.javaClass.simpleName
            }
        }
        return key
    }
}
